<?php
/* Extended Malcommunication Blocker : Anti-spam solution
----------------------------------

   Version 0.61

   Forked from      : EAS (Eolin Anti-spam Service Plugin, written by gendoh)
   Creator          : inureyes
   Maintainer       : inureyes

   Created at       : 2006.11.23
   Last modified at : 2008.6.16

 Version log
 -----------
 0.5.20080611

 This plugin blocks spams using trash information and EAS (Eolin Anti-spam Service).

 General Public License
 http://www.gnu.org/licenses/gpl.html

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
 modified by hina, 2008/12/19
 Change the rule about ip check, adding content,subject,url check with
 comment/trackback/guestbook.
 
*/

function EMB_Call($type, $name, $title, $url, $content)
{
	requireComponent('Eolin.PHP.Core');
	requireComponent('Eolin.PHP.XMLRPC');
	
	global $hostURL, $blogURL, $database;
	$blogstr = $hostURL . $blogURL;
	
	if(EMB_LocalCheck($blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']) == true) {

		$rpc = new XMLRPC();
		$rpc->url = 'http://antispam.eolin.com/RPC/index.php';
		if ($rpc->call('checkSpam', $blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']) == false) {	// EAS call failed
			return true;
			//return EMB_LocalCheck($blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']);
		}
		if (!is_null($rpc->fault)) {	// EAS does not respond
			// EAS has some problem
			return true;
			//return EMB_LocalCheck($blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']);
		}
	
		if ($rpc->result['result'] == true) {
			EMB_setCounter();
			EMB_DumpLog('Determined as spam by EAS.');
			EMB_AutomaticIPUpdater($type, $_SERVER['REMOTE_ADDR']);
			return false; // it's spam
		} else {
			return true;
			//return EMB_LocalCheck($blogstr, $type, $name, $title, $url, $content, $_SERVER['REMOTE_ADDR']);
		}
	} else {
		EMB_DumpLog('Spam check passed.');
		return false;
	}
}

function EMB_LocalCheck($blogstr, $type, $name, $title, $url, $content, $ip) {
	global $database;
	$count = 0;
	$tableName = $database['prefix'] . 'Trackbacks';
		
	if ($type == 2) { // Trackback Case
		$sql = 'SELECT COUNT(id) FROM ' . $database['prefix'] . 'Trackbacks WHERE ';
		$sql .= 'isFiltered > 0 AND ('.
			'url = \'' . POD::escapeString($url) . '\' '.
			'OR subject = \'' . POD::escapeString($title) . '\' '.
			'OR ip = \''. POD::escapeString($ip) . '\')';
		if ($result = POD::queryCell($sql)) {
			if(is_numeric($result)) $count += $result;
		}

	} else { // Comment or Guestbook Case
		$tableName = $database['prefix'] . 'Comments';	

		$sql = 'SELECT COUNT(id) FROM ' . $database['prefix'] . 'Comments WHERE ';
		$sql .= 'isFiltered > 0 AND replier = NULL AND '.
			'(comment = \'' . POD::escapeString($content) . '\' '.
			'OR homepage = \'' . POD::escapeString($url) . '\' '.
			'OR name = \'' . POD::escapeString($name) . '\' '.
			'OR ip = \''. POD::escapeString($ip) . '\')';
		
		if ($result = POD::queryCell($sql)) { 
			if(is_numeric($result)) $count += $result;
		}
	}

	// Check IP
	$sql = 'SELECT COUNT(id) as cc FROM ' . $tableName . ' WHERE';
	$sql .= ' ip = \'' . POD::escapeString($ip) . '\'';
	$sql .= ' AND isFiltered > 0';

	if ($result = POD::queryCell($sql)) {
		$count += $result;
	}
	
	if ($count > 9) {
		EMB_setCounter();
		EMB_AddIPFilter($ip);
		EMB_DumpLog('Determined as spam by EMB local scan.');
		return false;
	}
	return true;
}

function EMB_Ruminate() {
	// Ruminate currently added comments / trackbacks
	requireModel('blog.comment');
	requireModel('blog.trackback');
	requireComponent('Textcube.Function.Setting');
	global $database;
	$count = 0;
	$lastRuminate = setting::getServiceSetting('EASplusRmTime',0);
	$comments = POD::queryAll("SELECT blogid, id, entry, parent, name, homepage, secret, comment, ip, written, isFiltered
		FROM {$database['prefix']}Comments
		WHERE isFiltered = 0 AND written > $lastRuminate AND replier = NULL");
	if(isset($comments)) {
		foreach ($comments as $comment) {
			if(EMB_LocalCheck($hostURL.$blogURL, 1, $comment['name'], '', $comment['homepage'], $comment['comment'], $comment['ip'])===false) {
				trashComment($comment['blogid'],$comment['id'],$comment['entry'],null);
				$count = $count + 1;
			}
		}
	}
	$trackbacks = POD::queryAll("SELECT blogid, id, entry, site, subject, url, excerpt, written, isFiltered
		FROM {$database['prefix']}Trackbacks
		WHERE isFiltered = 0 AND written > $lastRuminate");
	if(isset($trackbacks)) {
		foreach ($trackbacks as $trackback) {
			if(EMB_LocalCheck($hostURL.$blogURL, 2, $trackback['site'], $trackback['subject'], $trackback['url'], $trackback['excerpt'], $trackback['ip'])===false) {
				trashTrackback($trackback['blogid'],$trackback['id']);
				$count = $count + 1;
			}
		}
	}
	if($count != 0) EMB_setCounter($count);
	setting::setServiceSetting('EASplusRmTime',Timestamp::getUNIXtime());
}

function EMB_AddingTrackback($target, $mother) {
	return EMB_Call(2, $mother['site'], $mother['title'], $mother['url'], $mother['excerpt']);
}

function EMB_AddingComment($target, $mother) {
//	if ($mother['secret'] ==  true) {// it's secret(only owner can see it)
		// Don't touch
//		return $target;
//	}
	
	$type = 1; // comment
	if ($mother['entry'] == 0) $type = 3; // guestbook
	return $target && EMB_Call($type, $mother['name'], '', $mother['homepage'], $mother['comment']);
}

function EMB_AutomaticIPUpdater($type, $ip) {
	global $database;
	$count = 0;
	if($type == 2) {
		$table = 'Trackbacks';
	} else {
		$table = 'Comments';
	}
	$count = POD::queryCell("SELECT COUNT(id) FROM ".$database['prefix'].$table."
		 WHERE isFiltered > 0 AND ip = '".$ip."'");
	if(is_numeric($count) && $count > 9) {
		EMB_AddIPFilter($ip);
	}
	return true;
}

function EMB_AddIPFilter($ip) {
	requireComponent('Textcube.Data.Filter');
	$filter = new Filter;
	$filter->type = 'ip';
	$filter->pattern = $ip;
	$result = $filter->add();
	return $result;
}

/***** UI-related part *****/
function EMB_setCounter($count = 1) {
	requireComponent('Textcube.Function.Setting');
	$currentCount = setting::getBlogSetting('EASBlockedPosts',0) + $count;
	setting::setBlogSetting('EASBlockedPosts',$currentCount);
}

function EMB_sidebar($target) {
	global $blog, $service;
	$blog['blogLanguage'] = $service['language'];

	requireComponent('Textcube.Function.Setting');
	$blockedCount = setting::getBlogSetting('EASBlockedPosts',0);
	$target = "<div class=\"listbox\">\n";
	switch($blog['blogLanguage']) {
		case "zh-TW":
			$target .= "<h3>EMB 插件</h3>\n";
			$target .= "EMB 插件阻擋了 ".$blockedCount." 個 SPAM.";
		break;
		case "zh-CN":
			$target .= "<h3>EMB 插件</h3>\n";
			$target .= "EMB 插件阻挡了 ".$blockedCount." 个 SPAM.";
		break;
		case "en":
			$target .= "<h3>EMB Plugin</h3>\n";
			$target .= "EMB plugin blocked ".$blockedCount." SPAM.";
		break;
		default:
			$target .= "<h3>EMB 통계</h3>\n";
			$target .= "EMB 가 ".$blockedCount."개의 스팸을 막았습니다.";
	}
	$target .= "</div>";
	return $target;
}

function EMB_center($target) {
	global $blog, $service;
	$blog['blogLanguage'] = $service['language'];

	requireComponent("Textcube.Function.Setting");
	$blockedCount = setting::getBlogSetting('EASBlockedPosts',0);
	$target .='<center>';
	switch($blog['blogLanguage']) {
		case "zh-TW":
			$target .= "EMB 插件阻擋了 ".$blockedCount." 個 SPAM.";
		break;
		case "zh-CN":
			$target .= "EMB 插件阻挡了 ".$blockedCount." 个 SPAM.";
		break;
		case "en":
			$target .= "EMB plugin blocked ".$blockedCount." SPAM.";
		break;
		default:
			$target .= "EMB 가 ".$blockedCount."개의 스팸을 막았습니다.";
	}	$target .='</center>'.CRLF;
	return $target;
}

function EMB_DumpLog($data) {
    if(!is_dir(ROOT."/cache")) {
        @mkdir(ROOT."/cache");
        @chmod(ROOT."/cache",0777);
    }   
  
    $dumpFile = ROOT.'/cache/EMB.log';
    if(file_exists($dumpFile)) {
        $dumpedLog = @file_get_contents($dumpFile);
    } else {
        $dumpedLog = ''; 
    }   
    $dumpedLog = $dumpedLog.Timestamp::format5()." : ".print_r($data,true).CRLF;
	$dumpedLog = implode("\r\n", array_slice(explode("\r\n", $dumpedLog), -1000));
	
    $fileHandle = fopen($dumpFile,'w');
    fwrite($fileHandle, $dumpedLog);
    fclose($fileHandle);
}
?>
